/* NOTICE
 
    Jim - the Java Image Manager, copyright (c) 2005 - 2007 Grant Gardner 
 
    Jim is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Jim is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
    In addition, as a special exception, you are permitted to link this code
    with the 3rd party libraries required to compile this file and to
    distribute a linked combination including them. You must obey the
    GNU General Public License in all respects for all of the code except for
    those 3rd party libraries that are licenced under terms incompatible with the
    GNU General Public License.  
 
 
 NOTICE */

package au.com.lastweekend.jim.controller;

import java.awt.Image;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;

import au.com.lastweekend.jim.actions.DeleteSelectedFilesAction;
import au.com.lastweekend.jim.actions.FullScreenNavigationAction;
import au.com.lastweekend.jim.actions.ImportSelectedImagesAction;
import au.com.lastweekend.jim.actions.LaunchFolderChooserAction;
import au.com.lastweekend.jim.actions.MoveSelectedFilesAction;
import au.com.lastweekend.jim.actions.RotateAction;
import au.com.lastweekend.jim.actions.FullScreenNavigationAction.NavigationType;
import au.com.lastweekend.jim.actions.MoveSelectedFilesAction.MoveSelectedFilesController;
import au.com.lastweekend.jim.actions.RotateAction.RotateActionController;
import au.com.lastweekend.jim.imagebase.ImageManager;
import au.com.lastweekend.jim.model.ContactSheetBaseModel;
import au.com.lastweekend.jim.model.ContactSheetImageItem;
import au.com.lastweekend.jim.model.ContactSheetListItem;
import au.com.lastweekend.jim.model.ContactSheetSelectedItems;
import au.com.lastweekend.jim.model.ImageDirectoryModel;
import au.com.lastweekend.jim.swing.folderchooser.FolderChooser;
import au.com.lastweekend.jim.swing.folderchooser.FolderChooserController;
import au.com.lastweekend.jim.swing.folderchooser.ToolBarFolderChooser;
import au.com.lastweekend.jim.util.LoaderThread;
import au.com.lastweekend.jim.util.PreviewImageStruct;
import au.com.lastweekend.jim.util.ReadAheadSorter;
import au.com.lastweekend.jim.view.JimFullScreen;
import au.com.lastweekend.jim.view.JimFullScreen.JimFullScreenModel;

/**
 * @author ggardner
 * 
 */
public class FullScreenController
        implements
            FolderChooserController,
            MoveSelectedFilesController,
            SelectedImagesController,
            RotateActionController {

    public interface FullScreenParentController extends WorkController, SelectedImagesController, RotateActionController {

        JimFullScreenModel getFullScreenModel();

    }

    public class FullScreenWindowAdapter extends WindowAdapter {

        @Override
        public void windowClosed(WindowEvent e) {

            closeFullScreen();
        }

    }

    private static final Logger LOG = Logger.getLogger(FullScreenController.class);
    JimFullScreen fullScreen = null;
    private FullScreenParentController parentController;
    private Collection<Action> actions = new ArrayList<Action>();
    private JimFullScreenModel model;
    private int curFrame;
    private List<ContactSheetListItem> images = Collections.emptyList();
    private LoaderThread<PreviewImageStruct, Image> loaderThread;
    private ContactSheetSelectedItems sourceItems;
    private WindowAdapter adapter = new FullScreenWindowAdapter();

    public FullScreenController(FullScreenParentController parentController) {

        this.parentController = parentController;
        this.model = parentController.getFullScreenModel();
        fullScreen = new JimFullScreen(model);

        initialiseActions();
        fullScreen.buildToolbar(actions);

        fullScreen.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        fullScreen.addWindowFocusListener(adapter);
        fullScreen.addWindowListener(adapter);

        startLoaderThread();

    }

    private void startLoaderThread() {

        loaderThread = new LoaderThread<PreviewImageStruct, Image>("FullScreenLoader", new ImagePanelLoader(fullScreen
                .getImagePanel(), model.getImageCache()));
        loaderThread.setDaemon(true);
        loaderThread.start();
    }

    private void initialiseActions() {

        actions.clear();

        actions.add(new LaunchFolderChooserAction(this));
        actions.add(new MoveSelectedFilesAction(this, true));
        actions.add(new DeleteSelectedFilesAction(this));
        actions.add(new ImportSelectedImagesAction(this));
        actions.add(new RotateAction(this, RotateAction.Rotation.ANTI_CLOCKWISE));
        actions.add(new RotateAction(this, RotateAction.Rotation.CLOCKWISE));

        actions.add(new FullScreenNavigationAction(this, NavigationType.PREVIOUS));
        actions.add(new FullScreenNavigationAction(this, NavigationType.NEXT));
        actions.add(new FullScreenNavigationAction(this, NavigationType.CLOSE));

    }

    public void open() {

        this.sourceItems = parentController.getSelectedItems();
        this.images = new ArrayList<ContactSheetListItem>(sourceItems.extractImageItems());
        if (images.size() > 0) {
            fullScreen.showGUI();
        } else {
            LOG.warn("No images selected");
        }

        curFrame = 0;

        if (images.size() > 0) {
            showCurrent();
        }
    }

    public File getCurrentDirectory() {

        ContactSheetBaseModel sourceModel = sourceItems.getModel();
        if (sourceModel instanceof ImageDirectoryModel) {
            return ((ImageDirectoryModel) sourceModel).getDirectory();
        }

        return null;
    }

    public FolderChooser getDialogFolderChooser() {

        return fullScreen.getDialogFolderChooser();
    }

    public ToolBarFolderChooser getToolBarFolderChooser() {

        return fullScreen.getToolBarFolderChooser();
    }

    /**
     * This is used by the various actions to operate on the selected items
     */
    public ContactSheetSelectedItems getSelectedItems() {

        ContactSheetBaseModel pseudoModel = new ContactSheetBaseModel() {

            public String getName() {

                return "Fullscreen";
            }

            public void refresh(final ContactSheetListItem imageItem) {

                sourceItems.getModel().refresh(imageItem);
            }

            public void reload() {

                sourceItems.getModel().reload();

            }
        };
        return new ContactSheetSelectedItems(pseudoModel, Collections.singletonList(images.get(curFrame)));
    }

    public void selectAllItems() {

    }

    public void doWork(Runnable work) {

        parentController.doWork(work);

    }

    public ImageManager getImageManager() {

        return parentController.getImageManager();
    }

    public boolean isRotateByTag() {

        return parentController.isRotateByTag();
    }

    public void showNext() {

        if (hasNext()) {
            curFrame++;

            if (currentExists()) {
                showCurrent();
            } else {
                showNext();
            }
        } else {
            if (images.size() > 0) {
                curFrame = 0;
                showCurrent();
            }
        }
    }

    private boolean currentExists() {

        return images.get(curFrame).getFile().exists();
    }

    private boolean hasNext() {

        return curFrame < images.size() - 1;
    }

    private void showCurrent() {

        String path = images.get(curFrame).getFile().getPath();

        if (!currentExists()) {
            LOG.debug("File missing possibly moved or deleted: " + path);
            showNext();
        } else {
            LOG.debug("Displaying " + path);

            int cacheSize = model.getImageCache().size();
            List<ContactSheetListItem> items = ReadAheadSorter.sort(images, curFrame, cacheSize);

            setPreviewItems(items);
        }
    }

    public void setPreviewItems(List<ContactSheetListItem> listItems) {

        List<PreviewImageStruct> previewItems = new ArrayList<PreviewImageStruct>();
        for (ContactSheetListItem listItem : listItems) {
            if (listItem != null && listItem.isPreviewAble()) {
                PreviewImageStruct pii = new PreviewImageStruct(listItem.getFile(), listItem.getRotationAngle());
                previewItems.add(pii);
            }

        }

        loaderThread.setSelected(previewItems);

    }

    public void showPrevious() {

        if (hasPrevious()) {
            curFrame--;
            if (currentExists()) {
                showCurrent();
            } else {
                showPrevious();
            }
        } else if (images.size() > 0) {
            curFrame = images.size() - 1;
            showCurrent();
        }

    }

    private boolean hasPrevious() {

        return images.size() > 0 && curFrame > 0;
    }

    public void closeFullScreen() {

        if (fullScreen.isShowing()) {
            fullScreen.closeFullScreen();
        }

    }

    public void updateImage(ContactSheetImageItem imageItem) {

        if (imageItem == images.get(curFrame)) {
            SwingUtilities.invokeLater(new Runnable() {

                public void run() {

                    showCurrent();

                }
            });
        }

    }

    public void resetSelection() {

        //nothing to do.
        
    }

}
